﻿using Api.Shared.Model;
using Api.Shared.Model.Common;
using Api.Shared.Model.Dto;
using Api.Shared.MyPlc.S7;
using Api.Shared.Sugar;
using Api.Shared.Utils;
using AutoMapper;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using S7.Net;
using SqlSugar;

namespace FitterTest.Controllers
{
    [Route("api/private/v1/[controller]/[action]")]
    [ApiController]
    [EnableCors("any")]
    public class DeviceController : ControllerBase
    {
        private readonly ISugarClientService helper;
        private readonly IMapper mapper;
        private readonly IS7ConnService s7;

        public DeviceController(
            [FromKeyedServices(nameof(SqlName.sqlite))] ISugarClientService helper,
            IMapper mapper,
            IS7ConnService s7
        )
        {
            this.helper = helper;
            this.mapper = mapper;
            this.s7 = s7;
        }

        [HttpPost]
        public async Task<IActionResult> UpLoad()
        {
            try
            {
                var files = Request.Form.Files;

                foreach (var file in files)
                {
                    if (file.Length > 0)
                    {
                        var uniqueFileName =
                            Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
                        var filePath = "E:\\TempPic";
                        var tempPath = Path.Combine(filePath, uniqueFileName); // 设置临时路径，用于存储上传的图片

                        using (var stream = new FileStream(tempPath, FileMode.Create))
                        {
                            await file.CopyToAsync(stream);
                        }
                        // Return the URL of the image file
                        //var imageUrl = $"{this.Request.Scheme}://{this.Request.Host}/{filePath}/{uniqueFileName}";

                        // 返回给前端的格式
                        //var response = new { pic = uniqueFileName, picUrl = imageUrl };

                        var imageUrl =
                            $"{this.Request.Scheme}://{this.Request.Host}/TempPic/{uniqueFileName}";
                        var response = new { pic = uniqueFileName, picUrl = imageUrl };
                        return Ok(response);
                    }
                }

                return BadRequest("未收到上传的图片。");
            }
            catch (Exception ex)
            {
                return StatusCode(
                    StatusCodes.Status500InternalServerError,
                    "上传图片时出错：" + ex.Message
                );
            }
        }

        [HttpPost]
        public async Task<IActionResult> AddDevice([FromBody] DeviceDto deviceDto)
        {
            var device = mapper.Map<Device>(deviceDto);

            int count = await this.helper.Db.Insertable<Device>(device).ExecuteCommandAsync();
            if (count > 0)
            {
                return Ok();
            }
            return StatusCode(204, "Failed");
        }

        [HttpGet]
        public async Task<IActionResult> GetDeviceList([FromQuery] QueryInfo queryInfo)
        {
            DB90Device? a = new();
            a = await s7.S7Plc.ReadClassAsync<DB90Device>(90, 0);

            if (a != null)
            {
                WriteMysql(a);
            }

            if (queryInfo.Pagenum <= 0)
            {
                return StatusCode(204, "Failed");
            }
            if (queryInfo.Pagesize <= 0)
            {
                return StatusCode(204, "Failed");
            }
            int totalNumber = 0;

            var exp = Expressionable.Create<Device>();
            exp.AndIF(
                !string.IsNullOrWhiteSpace(queryInfo.Query),
                x => x.DeviceName.Contains(queryInfo.Query)
            );

            var devices = helper
                .Db.Queryable<Device>()
                .Where(exp.ToExpression())
                .ToPageList(queryInfo.Pagenum, queryInfo.Pagesize, ref totalNumber);

            if (devices.Count > 0)
            {
                var devicesDto = mapper.Map<List<DeviceDto>>(devices);
                int bhq = 0,
                    hs = 0,
                    ddz = 0,
                    gy = 0,
                    gl = 0;
                if (a != null)
                {
                    if (a.ArcWireAlarmBool || a.ArcWirePreAlarmBool)
                    {
                        hs = 1;
                    }
                    if (a.GyAlarmBool || a.GyPreAlarmBool)
                    {
                        gy = 1;
                    }
                    if (a.GasAlarmBool || a.GasPreAlarmBool)
                    {
                        bhq = 1;
                    }
                    if (a.DdzAlarmBool || a.DdzPreAlarmBool)
                    {
                        ddz = 1;
                    }
                    if (a.HqPreAlarmBool || a.HqPreAlarmBool)
                    {
                        gl = 1;
                    }
                }
                var resultData = new
                {
                    total = totalNumber,
                    pagenum = queryInfo.Pagenum,
                    devicesDto = devicesDto,
                    classValue = 1,
                    bhq = bhq,
                    hs = hs,
                    gy = gy,
                    ddz = ddz,
                    gl = gl
                };

                return Ok(resultData);
            }
            return StatusCode(204, "Failed");
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateDevice(string id, [FromBody] Device device)
        {
            short.TryParse(device.PreAlarm, out short preAlarm);
            short.TryParse(device.Alarm, out short aAlarm);

            try
            {
                switch (device.DeviceNo)
                {
                    case "焊丝":
                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            0,
                            BigLittleChange(BitConverter.GetBytes(preAlarm))
                        );

                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            2,
                            BigLittleChange(BitConverter.GetBytes(aAlarm))
                        );

                        break;
                    case "导电嘴":
                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            8,
                            BigLittleChange(BitConverter.GetBytes(preAlarm))
                        );

                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            10,
                            BigLittleChange(BitConverter.GetBytes(aAlarm))
                        );

                        break;
                    case "保护气":
                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            4,
                            BigLittleChange(BitConverter.GetBytes(preAlarm))
                        );

                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            6,
                            BigLittleChange(BitConverter.GetBytes(aAlarm))
                        );

                        break;
                    case "焊枪管路":
                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            16,
                            BigLittleChange(BitConverter.GetBytes(preAlarm))
                        );

                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            18,
                            BigLittleChange(BitConverter.GetBytes(aAlarm))
                        );

                        break;
                    case "硅油":
                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            12,
                            BigLittleChange(BitConverter.GetBytes(preAlarm))
                        );

                        await s7.S7Plc.WriteBytesAsync(
                            DataType.DataBlock,
                            90,
                            14,
                            BigLittleChange(BitConverter.GetBytes(aAlarm))
                        );

                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                return StatusCode(204, $"Failed:{ex.Message}");
            }

            int count = await this.helper.Db.Updateable<Device>(device).ExecuteCommandAsync();
            if (count > 0)
            {
                return Ok();
            }

            return StatusCode(204, "Failed");
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetDeviceById(string id)
        {
            var device = await this.helper.Db.Queryable<Device>().InSingleAsync(int.Parse(id));
            if (device != null)
            {
                return Ok(device);
            }
            else
            {
                return StatusCode(204, "Failed");
            }
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> SetDeviceCommandById(string id)
        {
            try
            {
                Device device = await this
                    .helper.Db.Queryable<Device>()
                    .InSingleAsync(int.Parse(id));
                if (device == null)
                {
                    return StatusCode(204, "查询目录为空");
                }

                short.TryParse(device.PreAlarm, out short preAlarm);
                short.TryParse(device.Alarm, out short aAlarm);

                switch (device.DeviceNo)
                {
                    case "焊丝":
                        await s7.S7Plc.WriteBitAsync(DataType.DataBlock, 90, 29, 6, true);
                        break;
                    case "导电嘴":
                        await s7.S7Plc.WriteBitAsync(DataType.DataBlock, 90, 30, 0, true);
                        break;
                    case "保护气":
                        await s7.S7Plc.WriteBitAsync(DataType.DataBlock, 90, 29, 7, true);
                        break;
                    case "焊枪管路":
                        await s7.S7Plc.WriteBitAsync(DataType.DataBlock, 90, 30, 2, true);
                        break;
                    case "硅油":
                        await s7.S7Plc.WriteBitAsync(DataType.DataBlock, 90, 30, 1, true);
                        break;
                    default:
                        break;
                }

                return Ok();
            }
            catch (Exception ex)
            {
                return StatusCode(204, $"Failed{ex.Message}");
            }
        }

        // 修改 WriteMysql 方法，增加空值检查，防止 a 为空时解引用
        private int WriteMysql(DB90Device a)
        {
            if (a == null)
            {
                return 0;
            }

            var dev = helper.Db.Queryable<Device>().ToList();
            var hs = dev.Where(x => x.DeviceNo == "焊丝").First();
            var ddz = dev.Where(x => x.DeviceNo == "导电嘴").First();
            var bhq = dev.Where(x => x.DeviceNo == "保护气").First();
            var hq = dev.Where(x => x.DeviceNo == "焊枪管路").First();
            var gy = dev.Where(x => x.DeviceNo == "硅油").First();

            //焊丝
            hs.PreAlarm = a.ArcWirePreAlarm.ToString();
            hs.Alarm = a.ArcWireAlarm.ToString();
            hs.PreAlarmBool = a.ArcWirePreAlarmBool ? "已达预警值" : "正常";
            hs.AlarmBool = a.ArcWireAlarmBool ? "已达报警值" : "正常";

            //导电嘴
            ddz.PreAlarm = a.DdzPreAlarm.ToString();
            ddz.Alarm = a.DdzAlarm.ToString();
            ddz.PreAlarmBool = a.DdzPreAlarmBool ? "已达预警值" : "正常";
            ddz.AlarmBool = a.DdzAlarmBool ? "已达报警值" : "正常";

            //保护气
            bhq.PreAlarm = a.GasPreAlarm.ToString();
            bhq.Alarm = a.GasAlarm.ToString();
            bhq.PreAlarmBool = a.GasPreAlarmBool ? "已达预警值" : "正常";
            bhq.AlarmBool = a.GasAlarmBool ? "已达报警值" : "正常";

            //焊枪
            hq.PreAlarm = a.HqPreAlarm.ToString();
            hq.Alarm = a.HqAlarm.ToString();
            hq.PreAlarmBool = a.HqPreAlarmBool ? "已达预警值" : "正常";
            hq.AlarmBool = a.HqAlarmBool ? "已达报警值" : "正常";

            //硅油
            gy.PreAlarm = a.GyPreAlarm.ToString();
            gy.Alarm = a.GyAlarm.ToString();
            gy.PreAlarmBool = a.GyPreAlarmBool ? "已达预警值" : "正常";
            gy.AlarmBool = a.GyAlarmBool ? "已达报警值" : "正常";

            int count = helper.Db.Updateable(dev).ExecuteCommand();

            return count;
        }

        private byte[] BigLittleChange(byte[] b)
        {
            byte[] a = new byte[2];
            if (b.Length == 2)
            {
                a[0] = b[1];
                a[1] = b[0];
                return a;
            }
            else
            {
                return new byte[2];
            }
        }
    }
}
